package com.zhangc.blog.base;

import java.io.Serializable;

/**
 * 功能描述:<br>
 *
 * @author wx:fdzhangc
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public class ResultBO<T> implements Serializable {
    private static final ResultBO<?> EMPTY_DTO = new ResultBO<>();
    private static final long serialVersionUID = -5919315814636862305L;
    private final boolean success;
    private final String errorCode;
    private final String errorMsg;
    private final T data;

    private ResultBO() {
        this((T) null);
    }

    /**
     * 带数据data构造函数
     */
    private ResultBO(T data) {
        this(true, data, null, null);
    }

    private ResultBO(String errorCode, String errorMsg) {
        this(false, null, errorCode, errorMsg);
    }

    private ResultBO(boolean success, T data, String errorCode, String errorMsg) {
        this.success = success;
        this.data = data;
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
        if (this.data != null && !Serializable.class.isInstance(data)) {
            throw new BaseException("-1", "Data must implements Serializable.");
        }
    }

    public static <T> ResultBO<T> empty() {
        return (ResultBO<T>) EMPTY_DTO;
    }

    public static <T> ResultBO<T> success() {
        return empty();
    }

    public static <T> ResultBO<T> of(T value) {
        return value == null ? empty() : new ResultBO(value);
    }

    public static <T> ResultBO<T> error(T value) {
        return error(value, null, null);
    }

    public static <T> ResultBO<T> error(T value, String errorCode, String errorMsg) {
        return new ResultBO(false, value, errorCode, errorMsg);
    }

    public static <T> ResultBO<T> error500(T value) {
        return new ResultBO(false, value, "500", "服务器遇到了一个未曾预料的状况");
    }

    public static <T> ResultBO<T> error500() {
        return new ResultBO(false, null, "500", "服务器遇到了一个未曾预料的状况");
    }

    public static <T> ResultBO<T> errorParam() {
        return new ResultBO(false, null, "400", "请求参数有误");
    }

    public String getErrorCode() {
        return this.errorCode;
    }

    public String getErrorMsg() {
        return this.errorMsg;
    }

    public boolean isSuccess() {
        return this.success;
    }

    public T getData() {
        return this.data;
    }

    public String toString() {
        return String
                .format("ResultBO{success=%s, errorCode='%s', errorMsg='%s', data=%s}", this.success, this.errorCode, this.errorMsg,
                        this.data);
    }
}
